import tkinter as tk
import json
import math
import os
from PIL import Image, ImageTk  # 从Pillow库导入Image和ImageTk模块
# 读取 JSON 文件并转换为字典
def read_json_to_map(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        data = json.load(file)  # 解析 JSON 文件内容为字典
    return data


class DependeceLine:
    def __init__(self, canvas, x1=0, y1=0, x2=100, y2=100, radius = 32, line_color="white", line_width=2):
        """
        初始化 DependeceLine 类，在指定的 canvas 上绘制直线
        :param canvas: 传入的 Canvas 对象
        :param x1: 直线起点的 x 坐标
        :param y1: 直线起点的 y 坐标
        :param x2: 直线终点的 x 坐标
        :param y2: 直线终点的 y 坐标
        :param line_color: 直线的颜色
        :param line_width: 直线的宽度
        """
        self.canvas = canvas  # 传入的画布对象

        # 提取坐标
        self.x1 = x1  + 40
        self.x2 = x2  + 40
        self.y1 = y1
        self.y2 = y2
        self.radius = radius

        self.line_color = line_color
        self.line_width = line_width

        # 调用绘制方法
        self.draw_line()

    def draw_line(self):
        # 计算方向向量
        dx = self.x2 - self.x1
        dy = self.y2 - self.y1

        # 计算两圆心之间的距离
        dist = math.sqrt(dx**2 + dy**2)

        # 防止圆心重合时出错
        if dist == 0:
            return
        # 计算第一个圆的边缘点
        self.edge_x1 = self.x1 + (self.radius / dist) * dx
        self.edge_y1 = self.y1 + (self.radius / dist) * dy

        # 计算第二个圆的边缘点
        self.edge_x2 = self.x2 - (self.radius / dist) * dx
        self.edge_y2 = self.y2 - (self.radius / dist) * dy

        """在传入的画布上绘制一条直线"""
        self.line = self.canvas.create_line(
            self.edge_x1, self.edge_y1, self.edge_x2, self.edge_y2,
            fill=self.line_color, width=self.line_width
        )
    def on_resize(self, scale_x, scale_y, scale):
        self.x1 = self.x1 * scale_x
        self.x2 = self.x2 * scale_x
        self.y1 = self.y1 * scale_y
        self.y2 = self.y2 * scale_y
        self.radius = self.radius * scale
        if self.line is not None:
            self.canvas.delete(self.line)
        self.draw_line()


class TalentCircle(tk.Frame):
    def __init__(self, parent, canvas, center_x, center_y, radius, text_content, image_path):
        """
        创建一个带有悬停文本的圆圈。
        
        参数:
        - parent: 父容器
        - center_x: 圆心 X 坐标
        - center_y: 圆心 Y 坐标
        - radius: 圆的半径
        - text_content: 鼠标悬停时显示的文本内容
        """
        super().__init__(parent)
        
        # 初始化 Canvas
        self.canvas = canvas;
        self.width = 900
        self.height = 500
        
        # 圆心和半径
        self.center_x = center_x + 40
        self.center_y = center_y
        self.radius = radius
        self.text_content = text_content
        self.image_path = image_path
        
        self.draw()
 
    def draw(self):
        # 计算矩形坐标
        x0 = self.center_x - self.radius
        y0 = self.center_y - self.radius
        x1 = self.center_x + self.radius
        y1 = self.center_y + self.radius
        
        # 绘制圆圈
        self.circle = self.canvas.create_oval(x0, y0, x1, y1, outline="white", width=2, fill="black")
        
        # 使用Pillow加载WebP图片
        image = Image.open(self.image_path)  # 使用Pillow打开WebP图片

        # 计算目标图片大小（例如，圆的直径）
        target_size = int(2 * self.radius)
        
        # 缩放图片到目标大小
        image = image.resize((target_size, target_size), Image.Resampling.LANCZOS)

        self.image = ImageTk.PhotoImage(image)  # 转换为tkinter可用的格式
        
        # 在圆圈中心添加图片
        self.image_id = self.canvas.create_image(self.center_x, self.center_y, image=self.image)
        
        # 隐藏的文本对象，初始时不显示
        self.popup = None
        
        # 绑定鼠标事件
        self.canvas.tag_bind(self.image_id, "<Enter>", self.show_popup)  # 鼠标进入图片
        self.canvas.tag_bind(self.image_id, "<Leave>", self.hide_popup)  # 鼠标离开图片

    def on_resize(self, scale_x, scale_y, scale):
        self.current_scale = max(scale_x, scale_y)
        self.center_x = self.center_x * scale_x
        self.center_y = self.center_y * scale_y
        self.radius = self.radius * scale

        if self.circle is not None:
            self.canvas.delete(self.circle)
        if self.image_id is not None:
            self.canvas.delete(self.image_id)
        self.draw()

    def show_popup(self, event):
        """鼠标悬停时显示弹窗"""
        if self.popup is None:  # 确保只有一个弹窗
            self.popup = tk.Toplevel(self)
            self.popup.wm_overrideredirect(True)  # 移除弹窗标题栏
            self.popup.geometry(f"150x50+{event.x_root+10}+{event.y_root+10}")  # 弹窗位置
            # 弹窗内容
            label = tk.Label(self.popup, text='\n'.join(self.text_content),
                             padx=10, pady=5 , wraplength=150)
            label.pack()

    def hide_popup(self, event):
        """鼠标离开时关闭弹窗"""
        if self.popup is not None:
            self.popup.destroy()  # 销毁弹窗
            self.popup = None


class SmallTalentCircle(TalentCircle):
    def __init__(self, parent, canvas, center_x, center_y, radius, text_content, image_path):
        super().__init__(parent, canvas, center_x, center_y, radius, text_content, image_path)


class CoreTalentCircle(TalentCircle):
    def __init__(self, parent, canvas, center_x, center_y, radius, text_content, image_path):
        super().__init__(parent, canvas, center_x, center_y, radius, [text_content], image_path)

    def show_popup(self, event):
        """鼠标悬停时显示弹窗"""
        if self.popup is None:  # 确保只有一个弹窗
            self.popup = tk.Toplevel(self)
            self.popup.wm_overrideredirect(True)  # 移除弹窗标题栏
            self.popup.pack_propagate(True)
            self.popup.geometry(f"150x50+{event.x_root+10}+{event.y_root+10}")  # 弹窗位置
            # 弹窗内容
            label = tk.Label(self.popup, text=self.text_content[0], 
                             padx=10, pady=15 , wraplength=100)
            label.pack()

class SmallTalent():
    def __init__(self, talent_name, data, talent_pad, img_save_dir, width, height):
        self.talent_name = talent_name
        self.data = data
        self.talent_pad = talent_pad
        self.img_save_dir = img_save_dir
        self.talent_circles = []
        self.depence_lines  = []
        self.width = width
        self.height = height
        self.talent_pad.delete("all")

    def draw_small_talent(self):
        for i in self.data :
            talent = self.data[i]
            talent_circle = SmallTalentCircle(self.talent_pad, self.talent_pad, center_x=int(talent['x']), center_y=int(talent['y']), 
                                            radius=32, text_content=talent['descriptions'], image_path = os.path.join(self.img_save_dir, talent['img_url'].split('/')[-1]))
            self.talent_circles.append(talent_circle)
            if(talent['dependce'] != None):
                depence = self.data[str(talent['dependce'])]
                line = DependeceLine(self.talent_pad, x1=int(depence['x']), y1=int(depence['y']), x2=int(talent['x']), y2=int(talent['y']), line_width=2)
                self.depence_lines.append(line)
        return self.talent_circles, self.depence_lines

    def on_resize(self, event):
        scale_x = event.width / self.width
        scale_y = event.height / self.height
        scale = event.width * event.height / (self.width * self.height)
        self.width = event.width
        self.height = event.height
        for circle in self.talent_circles:
            circle.on_resize(scale_x, scale_y, scale)
        for line in self.depence_lines:
            line.on_resize(scale_x, scale_y, scale)

class CoreTalent():
    def __init__(self, talent_name, data, core_talent_pad, img_save_dir, width, height):
        self.talent_name = talent_name
        self.data = data
        self.core_talent_pad = core_talent_pad
        self.img_save_dir = img_save_dir
        self.talent_circles = []
        self.width = width
        self.height = height
        self.core_talent_pad.delete("all")
    
    def draw(self):
        for i in self.data:
            if int(i) == 3:
                pad = 80
            else:
                pad = 20
            talent = self.data[i]
            talent_circle = CoreTalentCircle(self.core_talent_pad, self.core_talent_pad, 
                                             center_x=int(i)*150+20, center_y=50, 
                                radius=10, text_content=talent['descriptions'], image_path = os.path.join(self.img_save_dir, talent['img_url'].split('/')[-1]))
            self.talent_circles.append(talent_circle)
            

    def on_resize(self, event):
        scale_x = event.width / self.width
        scale_y = 1
        scale = event.width * event.height / (self.width * self.height)
        self.width = event.width
        self.height = event.height
        for circle in self.talent_circles:
            circle.on_resize(scale_x, scale_y, scale)

class DrawSwitchTalent():
    def __init__(self):
        print("DrawSwitchTalent")

class TalentData():
    talent_data = None
    talent_group_map = None
    def __init__(self):
        self.list_path = "./out/talent_list.txt"
        if TalentData.talent_data is None or TalentData.talent_group_map is None:
            TalentData.talent_data, TalentData.talent_group_map = self.ReadTalentData()
    def ReadTalentData(self):
        if TalentData.talent_data is not None and TalentData.talent_group_map is not None:
            return TalentData.talent_data, TalentData.talent_group_map
        try:
            talent_name_map = read_json_to_map(self.list_path)
            
            talent_list = [item for group in talent_name_map for item in group]
            base_talent_list = [item for item in talent_list[0::4]]
            
            talent_group_map = {}
            for i, base_talent in enumerate(base_talent_list):
                talent_group_map[base_talent[0]] = talent_list[i*4+1:i*4+4]
            
            talent_data = {}
            
            for talent in talent_list:
                path_bath = f"./out/talent_{talent[1]}.txt"
                talent_data[talent[0]] = {'data': read_json_to_map(path_bath), 'url':talent[2]}
            return talent_data, talent_group_map

        except Exception as e:
            print(f"读取 JSON 文件失败: {e}")
